'\" t
.\"     Title: gpscsv
.\"    Author: Gary E. Miller
.\" Generator: Asciidoctor 2.0.18
.\"      Date: 2023-01-10
.\"    Manual: GPSD Documentation
.\"    Source: GPSD, Version 3.25
.\"  Language: English
.\"
.TH "GPSCSV" "1" "2023-01-10" "GPSD, Version 3.25" "GPSD Documentation"
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.ss \n[.ss] 0
.nh
.ad l
.de URL
\fI\\$2\fP <\\$1>\\$3
..
.als MTO URL
.if \n[.g] \{\
.  mso www.tmac
.  am URL
.    ad l
.  .
.  am MTO
.    ad l
.  .
.  LINKSTYLE blue R < >
.\}
.SH "NAME"
gpscsv \- dump the JSON output from gpsd as CSV
.SH "SYNOPSIS"
.sp
\fBgpscsv\fP [OPTIONS] [host[:port[:device]]]
.sp
\fBgpscsv\fP \-h
.sp
\fBgpscsv\fP \-V
.SH "DESCRIPTION"
.sp
\fBgpscsv\fP is a simple Python program for reading \fBgpsd\fP JSON data streams
and outputting them in Comma Separated Values (CSV) format. It takes
input from a specified \fBgpsd\fP and reports to standard output. The program
runs until the \fBgpsd\fP dies, "\fB\-n COUNT\fP" messages are processed,
"\fB\-x SECONDS\fP" have passed, or it is interrupted by ^C or other means.
.sp
\fBgpscsv\fP can only collect data that your \fBgpsd\fP is already sending.  Use
\fBgpspipe\fP to see what JSON message classes it is sending.
.sp
One good use of \fBgpscsv\fP is to create CSV files for use with the gnuplot
program.
.sp
\fBgpscsv\fP does not need root, but will run fine as root.
.SH "OPTIONS"
.sp
The program accepts the following options:
.sp
\fB\-?\fP, \fB\-h\fP, \fB\-\-help\fP
.RS 4
Show help information and exit.
.RE
.sp
\fB\-c MCLASS\fP, \fB\-\-class MCLASS\fP
.RS 4
Select the JSON class messages of type MCLASS. Overrides the default
class of TPV.  See the CLASSES section below for more information.
.RE
.sp
\fB\-\-cvt\-isotime\fP
.RS 4
Convert fields named "time" from ISO time to UNIX time.
.RE
.sp
\fB\-D LVL\fP, \fB\-\-debug LVL\fP
.RS 4
Set debug level to LVL. Default 0. Higher arguments than 0 produce
more debug output.
.RE
.sp
\fB\-\-device DEVICE\fP
.RS 4
The DEVICE on the \fBgpsd\fP to connect to. Defaults to all.
.RE
.sp
\fB\-f FIELDS\fP, \fB\-fields FIELDS\fP
.RS 4
The FIELDS from the JSON message to dump to the output. Set FIELD to
empty (\*(Aq\*(Aq) for all initially seen fields. Default varies by CLASS.
.RE
.sp
\fB\-\-file FILE\fP
.RS 4
Read JSON from FILE instead of from \fBgpsd\fP.
.RE
.sp
\fB\-\-header HEADER\fP
.RS 4
Set header style to HEADER. 0 for no header, 1 output fields as
header, 2 send fields as a comment (\*(Aq#\*(Aq). Defaults to 1.
.RE
.sp
\fB\-\-host HOST\fP
.RS 4
Connect to the \fBgpsd\fP on HOST. Defaults to localhost.
.RE
.sp
\fB\-n COUNT\fP, \fB\-\-count COUNT\fP
.RS 4
Exit after outputting COUNT records. Set COUNT to 0 to disable.
Default is 0
.RE
.sp
\fB\-\-port PORT\fP
.RS 4
Use PORT to connect to \fBgpsd\fP. Defaults to 2947.
.RE
.sp
\fB\-\-separator SEPARATOR\fP
.RS 4
Use SEPARATOR as the field separator. Default separator is a comma
(\*(Aq,\*(Aq).
.RE
.sp
\fB\-V\fP, \fB\-\-version\fP
.RS 4
Show \fBgpscsv\fP version, and exit.
.RE
.sp
\fB\-x SECONDS\fP, \fB\-\-seconds SECONDS\fP
.RS 4
Exit after SECONDS number of seconds have passed. Set SECONDS to 0 to
disable. Default is 0
.RE
.sp
All the above individual options may be specified multiple times, but  t
only the last one off each will be used.
.SH "CLASSES"
.sp
Some of the \fBgpsd\fP JSON message classes include sub\-classes.  \fBgpscsv\fP
allows direct access to them using a meta\-class (MCLASS).
.TS
allbox tab(:);
lt lt lt.
T{
.sp
MCLASS
T}:T{
.sp
Class
T}:T{
.sp
Description
T}
T{
.sp
ALMANAC
T}:T{
.sp
SUBFRAME
T}:T{
.sp
ALMANAC from SUBFRAME JSON
T}
T{
.sp
HEALTH
T}:T{
.sp
SUBFRAME
T}:T{
.sp
HEALTH from SUBFRAME JSON
T}
T{
.sp
HEALTH2
T}:T{
.sp
SUBFRAME
T}:T{
.sp
HEALTH2 from SUBFRAME JSON
T}
T{
.sp
IONO
T}:T{
.sp
SUBFRAME
T}:T{
.sp
IONO from SUBFRAME JSON
T}
T{
.sp
NMCT
T}:T{
.sp
SUBFRAME
T}:T{
.sp
NMCT from SUBFRAME JSON
T}
T{
.sp
SUBFRAME1
T}:T{
.sp
SUBFRAME
T}:T{
.sp
SUBFRAME1 (Ephemeris 1) from SUBFRAME JSON
T}
T{
.sp
SUBFRAME2
T}:T{
.sp
SUBFRAME
T}:T{
.sp
SUBFRAME2 (Ephemeris 2) from SUBFRAME JSON
T}
T{
.sp
SUBFRAME3
T}:T{
.sp
SUBFRAME
T}:T{
.sp
SUBFRAME3 (Ephemeris 3) from SUBFRAME JSON
T}
T{
.sp
SAT
T}:T{
.sp
SKY
T}:T{
.sp
Individual satellites from SKY
T}
T{
.sp
SKY
T}:T{
.sp
SKY
T}:T{
.sp
The basic parts of SKY JSON
T}
T{
.sp
TPV
T}:T{
.sp
TPV
T}:T{
.sp
The basic parts of TPV JSON
T}
.TE
.sp
.SH "ARGUMENTS"
.sp
By default, clients collect data from the local \fBgpsd\fP daemon running
on localhost, using the default GPSD port 2947. The optional argument
to any client may override this behavior: \fB[server[:port[:device]]]\fP
.sp
For further explanation, and examples, see the \fBARGUMENTS\fP section in
the \fBgps\fP(1) man page
.SH "EXAMPLES"
.sp
Some basic standalone examples:
.sp
Grab three cycles of TPV data:
.sp
.if n .RS 4
.nf
.fam C
$ gpscsv \-c TPV \-n 3
time,lat,lon,altHAE
2021\-07\-28T22:38:37.000Z,44.0688638,\-121.3140643,1108.223
2021\-07\-26T22:38:37.000Z,44.068863833,\-121.314064333,1108.3
2021\-07\-28T22:38:38.000Z,44.0688637,\-121.314065,1108.363
.fam
.fi
.if n .RE
.sp
Grab one set of satellite data:
.sp
.if n .RS 4
.nf
.fam C
$ gpscsv \-c SAT \-n 1
time,gnssid,svid,PRN,az,el,ss,used,health
2021\-07\-28T22:37:46.000Z,0,8,8,311.0,28.0,33.0,True,1
2021\-07\-28T22:37:46.000Z,0,10,10,290.0,74.0,50.0,True,1
2021\-07\-28T22:37:46.000Z,0,15,15,45.0,18.0,31.0,False,1
2021\-07\-28T22:37:46.000Z,0,16,16,244.0,7.0,23.0,True,1
2021\-07\-28T22:37:46.000Z,0,18,18,109.0,43.0,37.0,True,1
2021\-07\-28T22:37:46.000Z,0,23,23,49.0,62.0,38.0,True,1
2021\-07\-28T22:37:46.000Z,0,24,24,87.0,16.0,28.0,True,1
2021\-07\-28T22:37:46.000Z,0,27,27,280.0,52.0,42.0,True,1
2021\-07\-28T22:37:46.000Z,0,32,32,188.0,32.0,42.0,True,1
2021\-07\-28T22:37:46.000Z,5,3,195,305.0,6.0,13.0,False,1
2021\-07\-28T22:37:46.000Z,6,2,66,38.0,8.0,21.0,False,1
2021\-07\-28T22:37:46.000Z,6,3,67,34.0,60.0,32.0,True,1
2021\-07\-28T22:37:46.000Z,6,4,68,226.0,63.0,34.0,True,1
2021\-07\-28T22:37:46.000Z,6,5,69,220.0,12.0,32.0,True,1
2021\-07\-28T22:37:46.000Z,6,11,75,\-999,4.0,0.0,False,2
2021\-07\-28T22:37:46.000Z,6,12,76,47.0,0.0,0.0,False,1
2021\-07\-28T22:37:46.000Z,6,17,81,142.0,8.0,31.0,True,1
2021\-07\-28T22:37:46.000Z,6,18,82,138.0,57.0,40.0,True,1
2021\-07\-28T22:37:46.000Z,6,19,83,333.0,70.0,29.0,True,1
2021\-07\-28T22:37:46.000Z,6,20,84,323.0,10.0,0.0,False,1
.fam
.fi
.if n .RE
.SS "Plot Examples"
.sp
Some plot examples, do them in exact order shown:
.sp
Grab 100 samples of time,lat,lon,altHAE:
.sp
.if n .RS 4
.nf
.fam C
  $ gpscsv \-n 100 \-\-cvt\-isotime  > tpv.dat
.fam
.fi
.if n .RE
.sp
Grab 100 samples of time,epx,epy,epv,eph,sep
.sp
.if n .RS 4
.nf
.fam C
  $ gpscsv \-n 100 \-\-cvt\-isotime \-f time,epx,epy,epv,eph,sep > ep.dat
.fam
.fi
.if n .RE
.sp
Grab 100 samples of time,xdop,ydop,vdop,tdop,hdop,gdop,pdop
.sp
.if n .RS 4
.nf
.fam C
  $ gpscsv \-n 100 \-\-cvt\-isotime \-c SKY  > sky.dat
.fam
.fi
.if n .RE
.sp
Grab 100 samples of time,nSat,uSat
.sp
.if n .RS 4
.nf
.fam C
  $ gpscsv \-n 100 \-\-cvt\-isotime \-c SKY \-f time,nSat,uSat  > sat.dat
.fam
.fi
.if n .RE
.SS "Viewing CSV data with gnuplot"
.sp
Start gnuplot in interactive mode:
.sp
.if n .RS 4
.nf
.fam C
  $ gnuplot
.fam
.fi
.if n .RE
.sp
Some gnuplot housekeeping:
.sp
.if n .RS 4
.nf
.fam C
  # this are csv files
  gnuplot> set datafile separator \*(Aq,\*(Aq
  # use the first line as title
  gnuplot> set key autotitle columnhead
  # X axis is UNIT time in seconds.
  gnuplot> set xdata time
  gnuplot> set timefmt "%s"
.fam
.fi
.if n .RE
.sp
Now to plot time vs latitude, using \fBtpv.dat\fP from above:
.sp
.if n .RS 4
.nf
.fam C
  gnuplot> plot \*(Aqtpv.dat\*(Aq using 1:2
.fam
.fi
.if n .RE
.sp
Then to plot longitude and altHAE, in separate plots:
.sp
.if n .RS 4
.nf
.fam C
  gnuplot> plot \*(Aqtpv.dat\*(Aq using 1:3
  gnuplot> plot \*(Aqtpv.dat\*(Aq using 1:4
.fam
.fi
.if n .RE
.sp
Put both latitude and longitude on one plot:
.sp
.if n .RS 4
.nf
.fam C
  gnuplot> set y2tics
  gnuplot> plot \*(Aqtpv.dat\*(Aq using 1:2, \*(Aq\*(Aq using 1:3 axes x1y2
.fam
.fi
.if n .RE
.sp
Plot epx, epy, epv, eph, and sep in one plot, using \fBep.dat\fP from above:
.sp
.if n .RS 4
.nf
.fam C
  gnuplot> plot \*(Aqep.dat\*(Aq using 1:2, \*(Aq\*(Aq using 1:3, \(rs
           \*(Aq\*(Aq using 1:4, \*(Aq\*(Aq using 1:5, \*(Aq\*(Aq using 1:6
.fam
.fi
.if n .RE
.sp
Plot all the DOPs on one plot, from \fBsky.dat\fP above:
.sp
.if n .RS 4
.nf
.fam C
  gnuplot> plot \*(Aqsky.dat\*(Aq using 1:2, \*(Aq\*(Aq using 1:3, \*(Aq\*(Aq using 1:4, \(rs
           \*(Aq\*(Aq using 1:5, \*(Aq\*(Aq using 1:6, \*(Aq\*(Aq using 1:7, \*(Aq\*(Aq using 1:8
.fam
.fi
.if n .RE
.sp
Plot nSat and uSat together:
.sp
.if n .RS 4
.nf
.fam C
  gnuplot> plot \*(Aqsat.dat\*(Aq using 1:2, \*(Aq\*(Aq using 1:3
.fam
.fi
.if n .RE
.sp
Lat/lon scatter plot:
.sp
.if n .RS 4
.nf
.fam C
  # x is no longer time
  gnuplot> set xdata
  gnuplot> plot \*(Aqtpv.dat\*(Aq using 3:2 title \*(Aqfix\*(Aq
.fam
.fi
.if n .RE
.SH "RETURN VALUES"
.sp
\fB0\fP
.RS 4
on success.
.RE
.sp
\fB1\fP
.RS 4
on failure
.RE
.SH "SEE ALSO"
.sp
\fBgpspipe\fP(1), \fBgpsd_json\fP(5), \fBgpsd\fP(8), \fBgnuplot\fP(1)
.SH "RESOURCES"
.sp
\fBProject web site:\fP \c
.URL "https://gpsd.io/" "" ""
.SH "COPYING"
.sp
This file is Copyright 2020 by the GPSD project
.br
SPDX\-License\-Identifier: BSD\-2\-clause
.SH "AUTHOR"
.sp
Gary E. Miller